/*
 * @Author: wuqingchun
 * @Date: 2024-07-16 18:57:26
 * @Description: 一次分配固定内存大小的内存管理器
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-07-16 20:05:06
 */

#include <cstdint>
#include <cstddef>

#include <iostream>

#include "mem_time.h"

template <typename T>
class MemoryPoolFixsize
{
private:
    static constexpr uint32_t EXPANSION_COUNT = 32;
public:
    MemoryPoolFixsize(uint32_t uiCount)
    {
        m_pobNext = nullptr;
        __ExpandFreeList(uiCount);
    }
    
    ~MemoryPoolFixsize()
    {
        for (MemoryPoolFixsize<T>* pobjCur = m_pobNext; pobjCur != nullptr; pobjCur = m_pobNext)
        {
            m_pobNext = pobjCur->m_pobNext;
            delete[] (char*)pobjCur;
        }
    }

    void* Alloc()
    {
        if (m_pobNext == nullptr)
        {
            __ExpandFreeList(EXPANSION_COUNT);
        }

        MemoryPoolFixsize<T>* pobHead = m_pobNext;
        m_pobNext = pobHead->m_pobNext;

        return pobHead;
    }

    void Free(void* pMem)
    {
        if (pMem != nullptr)
        {
            ((MemoryPoolFixsize<T>*)pMem)->m_pobNext = m_pobNext;
            m_pobNext = (MemoryPoolFixsize<T>*)pMem;
        }
    }

private:
    void __ExpandFreeList(uint32_t uiCount)
    {
        size_t ulSize = sizeof(T) > sizeof(MemoryPoolFixsize<T>*) ? sizeof(T) : sizeof(MemoryPoolFixsize<T>*);
        MemoryPoolFixsize<T>* pobNew;
        for (uint32_t uiTmp = 0; uiTmp < uiCount; uiTmp++)
        {
            pobNew = reinterpret_cast<MemoryPoolFixsize<T>*> (new (std::nothrow) char[ulSize]);
            if (pobNew != nullptr)
            {
                pobNew->m_pobNext = m_pobNext;
                m_pobNext = pobNew;
            }
        }
    }
private:
    MemoryPoolFixsize<T>* m_pobNext;
};


class Rational
{
public:
    Rational(int iNumerator=0, int iDenominator=1):
        m_iNumerator(iNumerator),
        m_iDenominator(iDenominator)
    {
    }
    void* operator new(size_t ulSize)
    {
        m_pobjMemPool->Alloc();
    }

    void operator delete(void* pMem, size_t ulSize)
    {
        m_pobjMemPool->Free(pMem);
    }

    static void newMemPool()
    {
        m_pobjMemPool = new MemoryPoolFixsize<Rational>(1024);
    }

    static void deleteMemPool()
    {
        delete m_pobjMemPool;
    }

private:
    static MemoryPoolFixsize<Rational>* m_pobjMemPool;
private:
    int m_iNumerator;
    int m_iDenominator;
};

MemoryPoolFixsize<Rational>* Rational::m_pobjMemPool = nullptr;

int main(int argc, char** argv)
{
    Rational* apobjRational[1000];
    Rational::newMemPool();

    uint64_t ui64BeginUS, ui64EndUS;
    
    TIMESTAMP_NOW_US(ui64BeginUS);
    // 开始计时
    for (int i = 0; i < 500; i++)
    {
        for (int j = 0; j < 1000; j++)
        {
            apobjRational[j] = new Rational(i);
        }

        for (int j = 0; j < 1000; j++)
        {
            delete apobjRational[j];
        }
    }

    TIMESTAMP_NOW_US(ui64EndUS);

    Rational::deleteMemPool();
    // 结束计时

    std::cout << "Elapsed(us): " << ui64EndUS - ui64BeginUS << std::endl;

    return 0;
}